/*
 * trader.cpp
 *
 *  Created on: 04/giu/2014
 *      Author: ammin
 */

#include "trader.h"
#include "nature.h"

using namespace NS_TRADER;
using namespace NS_NATURE;

Trader::Trader(NeuralNetworkMap *nnMap) : m_brain(nnMap){
	m_age = 0;
	ageState = AGE_CHILD;

	Nature *pNature = Nature::Instance();
	m_pBroker = pNature->GetSchoolTeacher();
	m_pBroker->Attach(this);

	Nature::Remove(pNature);
}

Trader::~Trader(){
	if(m_pBroker)
		m_pBroker->Detach(this);
}

void Trader::Begin(Ticker stockSeriesName){
	m_brain.ClearMind();

	m_currentSession.Init(stockSeriesName);
}

void Trader::Update(StockData &stockData){
	m_currentSession.lastStockData = stockData;
	m_brain.FeedData(	m_currentSession.lastStockData.timestamp,
						m_currentSession.lastStockData.open,
						m_currentSession.lastStockData.close,
						m_currentSession.lastStockData.min,
						m_currentSession.lastStockData.max,
						m_currentSession.lastStockData.tradedVol);
	GrowUp();
}

void Trader::Update(Strategy &forecast){
	Ticker stockName = m_currentSession.stockName;
	POSITION_TYPE _position = (forecast.portfolioInvestment < 0) ? POS_SHORT : POS_LONG;
	PRICE _entryPrice = forecast.entryPriceOnPrevClose * m_currentSession.lastStockData.close;
	PERCENT _takeProfit = forecast.takeProfit;
	PERCENT _stopLoss = forecast.stopLoss;
	int _nStock = forecast.portfolioInvestment * m_portfolio.GetAmount() / _entryPrice;

	if(_nStock){
		Order *pOrder = new Order(stockName, _position, _entryPrice, _takeProfit, _stopLoss, _nStock);
		m_pBroker->CommitOrder(pOrder, GetPortfolio());
	}
}

void Trader::CorrectStrategy(const Order *pOrderCorrected){
	Strategy correctedStrategy(	pOrderCorrected->m_entryPrice / m_currentSession.lastStockData.close,
								pOrderCorrected->m_takeProfit,
								pOrderCorrected->m_stopLoss,
								pOrderCorrected->m_nStock * pOrderCorrected->m_entryPrice / m_portfolio.GetAmount());

	m_brain.Learn(correctedStrategy);
}

NeuralNetworkMap *Trader::GetGeneticMap() const{
	return m_brain.GetMap();
}

Portfolio *Trader::GetPortfolio(){
	return &m_portfolio;
}

void Trader::GrowUp(){
	m_age++;

	switch(ageState){
	case AGE_CHILD:{
			Nature *pNature = Nature::Instance();
			if(pNature->IsAdult(m_age) == true){
				ageState = AGE_ADULT;
				m_pBroker->Detach(this);

				m_pBroker = pNature->GetStockExchangeBroker();
				m_pBroker->Attach(this);
			}
			Nature::Remove(pNature);
		}
		break;

	default:
		break;
	}
}
